home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib43 / mntlib / thread.c < prev    next >
C/C++ Source or Header  |  1994-01-15  |  3KB  |  141 lines

  1. /*
  2.  * tfork(function, argument): starts a new thread of execution running
  3.  * in the same address space. The new thread gets its own 4K stack,
  4.  * and starts at the address in "function" with "argument" on the stack,
  5.  * i.e. as though the main program had a call like "function(argument)".
  6.  * The main program continues executing, with tfork returning the process
  7.  * i.d. of the child.
  8.  * (if MiNT is not active, then the child runs to completion
  9.  *  and the return value is the child's exit status; vfork() relies on
  10.  *  this behavior)
  11.  *
  12.  * Note that parent and child share the same memory; this could cause
  13.  * problems with some library calls, notably malloc().
  14.  */
  15.  
  16. #include <compiler.h>
  17. #include <osbind.h>
  18. #include <basepage.h>
  19. #include <signal.h>
  20. #include <time.h>
  21. #include <unistd.h>
  22. #include <signal.h>
  23. #include <errno.h>
  24. #include <support.h>
  25. #include "lib.h"
  26.  
  27. #define SIZE 4096L
  28.  
  29. #ifdef __MBASE__    /* gcc -mbaserel data/bss base */
  30. #define mbasep() \
  31. ({    register long retvalue __asm__(__MBASESTR__);    \
  32.     retvalue;                    \
  33. })
  34. #define fixmbasep(addr) (void) \
  35. ({                        \
  36.     __asm__ volatile            \
  37.     (" movl    %0,"__MBASESTR__ ";"        \
  38.     :            /* outputs */    \
  39.     : "g"(addr)            /* inputs */    \
  40.     );                    \
  41. })
  42. #endif /* __MBASE__ */
  43.  
  44. extern int __mint;
  45. extern long _childtime;            /* in main.c */
  46. extern long _sigpending, _sigmask;    /* in signal.c */
  47. extern __Sigfunc _sig_handler[NSIG];    /* ditto */
  48.  
  49.  
  50. /* this is used by wait() and wait3() to retrieve the child's exit code */
  51. long __waitval = -ENOENT;
  52.  
  53. /* and this is used to retrieve the child's time */
  54. long __waittime = 0;
  55.  
  56. static void __CDECL startup __PROTO((BASEPAGE *));
  57.  
  58. static void __CDECL
  59. startup(b)
  60.     register BASEPAGE *b;
  61. {
  62.     register int (*func) __PROTO((long));
  63.     register long arg;
  64.  
  65. #ifdef __TURBOC__
  66.     extern void *_StkLim;    /* avoid stack checking */
  67.     _StkLim = NULL;
  68. #endif
  69.     _setstack( ((char *)b) + SIZE );
  70.     func = (int (*) __PROTO((long)))b->p_dbase;
  71.     arg = b->p_dlen;
  72. #ifdef __MBASE__
  73.     fixmbasep((long) (b->p_bbase));
  74. #endif /* __MBASE__ */
  75.     Pterm((*func)(arg));
  76. }
  77.  
  78. /* use long instead of int so vfork works OK with -mshort */
  79.  
  80. long
  81. tfork(func, arg)
  82.     int (*func) __PROTO((long));
  83.     long arg;
  84. {
  85.     register BASEPAGE *b;
  86.     register long pid;
  87.     register long savpending, savmask;
  88.     register BASEPAGE *savbase;
  89.     __Sigfunc savhandler[NSIG];
  90.     long now;
  91.     int i;
  92.  
  93.     b = (BASEPAGE *)Pexec(PE_CBASEPAGE, 0L, "", 0L);
  94.     (void)Mshrink(b, SIZE+256);
  95.     b->p_tbase = (char *)startup;
  96.     b->p_dbase = (char *)func;
  97.     b->p_dlen = arg;
  98.     b->p_hitpa = ((char *)b) + SIZE + 256;
  99. #ifdef __MBASE__
  100.     b->p_bbase = (char *) mbasep();
  101. #endif /* __MBASE__ */
  102.  
  103.     if (__mint)
  104.         pid = Pexec(104, 0L, b, 0L);
  105.     else {
  106.     /* save the signal masks and signal handlers, the child may change
  107.            them */
  108.         savpending = _sigpending;
  109.         _sigpending = 0;
  110.         savmask = _sigmask;
  111.         _sigmask = 0;
  112.         for (i = 0; i < NSIG; i++)
  113.             savhandler[i] = _sig_handler[i];
  114.         savbase = _base;
  115.         _base = b;
  116.  
  117.         now = _clock();
  118.         pid = Pexec(4, 0L, b, 0L);
  119.  
  120.         _base = savbase;
  121.     /* restore signal stuff */
  122.         for (i = 0; i < NSIG; i++)
  123.             _sig_handler[i] = savhandler[i];
  124.         _sigmask = savmask;
  125.         _sigpending = savpending;
  126.         if (pid >= 0) {
  127.             long retval = pid;
  128.  
  129.         /* see the TOS algorithm for getpid() */
  130.             pid = ((long)b) >> 8;
  131.             __waitval = (pid << 16) | retval;
  132.             raise(SIGCHLD);
  133.             __waittime = _clock() - now;
  134.             _childtime += __waittime;
  135.         }
  136.     }
  137.     (void)Mfree(b->p_env);    /* free the memory */
  138.     (void)Mfree(b);
  139.     return pid;
  140. }
  141.